const express = require("express")
const router = express.Router()
const adminDB = require("../../db/admin")
const jwt = require("jsonwebtoken")
const { supertubeRouter, admintorRouter } = require("../router")
const journalDB = require("../../db/journal")

// 密钥
const cort = "coderxinxin2022-04-15"

// 登录
router.post("/login", async (req, res) => {
  try {
    const { name, pass } = req.body
    // 校验输入信息
    if (!name.trim() || name.length < 2 || name.length > 12) {
      return res.send({
        code: 2,
        mes: "输入用户名不合法",
      })
    }
    if (!pass.trim() || pass.length < 6 || pass.length > 12) {
      return res.send({
        code: 2,
        mes: "输入密码不合法",
      })
    }
    // 查询账号是否存在
    const doc = await adminDB.findOne({ name })
    if (!doc)
      return res.send({
        code: 3,
        mes: "请使用管理员账号登录",
      })
    // 查询密码是否正确
    if (pass !== doc.pass)
      return res.send({
        code: 4,
        mes: "密码不正确，请重新输入",
      })

    // 登录成功
    // 生成token
    let token = jwt.sign(
      {
        // 传入的数据
        _id: doc._id,
        name,
        pass,
        // 有效时间
        exp: Math.floor(Date.now() / 1000) + 60 * 30, // 30分钟过期
      },
      cort
    )
    // 前端全局状态管理
    const vuexData = {
      _id: doc._id,
      name: doc.name,
      avatar: doc.avatar,
      des: doc.des,
      email: doc.email,
      phone: doc.phone,
      supertube: doc.supertube,
      admintor: doc.admintor,
      time: doc.time,
      cover: doc.cover,
      occupation: doc.occupation,
      messageList: doc.messageList,
      systemUnread: doc.systemUnread,
      festivalUnread: doc.festivalUnread,
      appointmentUnread: doc.appointmentUnread,
      startUnread: doc.startUnread,
    }

    res.send({
      code: 0,
      mes: "登录成功，欢迎回来",
      data: {
        token,
        vuexData,
      },
    })
  } catch (error) {
    res.send({
      code: 5,
      mes: "服务器异常，请稍后再试",
    })
  }
})

// 检测登录 保持登录状态
router.get("/check", async (req, res) => {
  try {
    // 校验token
    // 获取请求头里面的token
    let token = (req.headers.authorization || "").slice(7)
    let info = null
    // 捕获错误
    try {
      info = jwt.verify(token, cort)
      const doc = await adminDB.findById(info._id)
      if (!doc)
        return res.send({
          code: 4,
          mes: "系统检测到该账号已被注销",
        })
      // 检测密码是否更新
      if (info.pass !== doc.pass)
        return res.send({
          code: 4,
          mes: "密码已更新,请重新登录",
        })
      // 生成新的token
      const newToken = jwt.sign(
        {
          // 传入的数据
          _id: doc._id,
          name: doc.name,
          pass: doc.pass,
          // 有效时间
          exp: Math.floor(Date.now() / 1000) + 60 * 30, // 30分钟过期
        },
        cort
      )
      // 前端全局状态管理
      const vuexData = {
        _id: doc._id,
        name: doc.name,
        avatar: doc.avatar,
        des: doc.des,
        email: doc.email,
        phone: doc.phone,
        supertube: doc.supertube,
        admintor: doc.admintor,
        time: doc.time,
        cover: doc.cover,
        occupation: doc.occupation,
        messageList: doc.messageList,
        systemUnread: doc.systemUnread,
        festivalUnread: doc.festivalUnread,
        appointmentUnread: doc.appointmentUnread,
        startUnread: doc.startUnread,
      }
      res.send({
        code: 0,
        mes: "欢迎回来",
        data: {
          token: newToken,
          vuexData,
        },
      })
    } catch (error) {
      return res.send({
        code: 4,
        mes: "登录信息已过期,请重新登录",
      })
    }
  } catch (error) {
    res.send({
      code: 5,
      mes: "服务器异常，请稍后再试",
    })
  }
})

// 请求用户路由
router.get("/router", async (req, res) => {
  try {
    // 获取token
    let token = (req.headers.authorization || "").slice(7)
    let info = null
    // 捕获错误
    try {
      info = jwt.verify(token, cort)
      const doc = await adminDB.findById(info._id)
      if (!doc)
        return res.send({
          code: 4,
          mes: "系统检测到该账号已被注销",
        })
      let userMenu = []
      doc.supertube ? (userMenu = supertubeRouter) : (userMenu = admintorRouter)

      res.send({
        code: 0,
        mes: "用户菜单",
        data: {
          userMenu,
        },
      })
    } catch (error) {
      return res.send({
        code: 4,
        mes: "登录信息已过期,请重新登录",
      })
    }
  } catch (error) {
    res.send({
      code: 5,
      mes: "服务器异常，请稍后再试",
    })
  }
})

// 检测是否登录
router.use(async (req, res, next) => {
  try {
    // 校验token
    // 获取请求头里面的token
    let token = (req.headers.authorization || "").slice(7)
    let info = null
    // 捕获错误
    try {
      info = jwt.verify(token, cort)
      const doc = await adminDB.findById(info._id)
      if (!doc)
        return res.send({
          code: 4,
          mes: "系统检测到该账号已被注销",
        })
      // 检测密码是否更新
      if (info.pass !== doc.pass)
        return res.send({
          code: 4,
          mes: "密码已更新,请重新登录",
        })
      next()
    } catch (error) {
      console.log(error)
      return res.send({
        code: 4,
        mes: "登录信息已过期,请重新登录",
      })
    }
  } catch (error) {
    res.send({
      code: 5,
      mes: "服务器异常，请稍后再试",
    })
  }
})

// 修改信息 (非密码)
router.post("/update", async (req, res) => {
  try {
    let { userID, name, email, phone, occupation, des } = req.body
    // 查看用户名是否合法
    if (!name.trim() || name.length < 2 || name.length > 12) {
      return res.send({
        code: 2,
        mes: "用户名不合法",
      })
    }
    // 校验手机
    if (phone && phone !== "暂无填写" && phone.length !== 11) {
      return res.send({
        code: 2,
        mes: "手机格式不合法",
      })
    }
    // 查看邮件
    if (!email.trim() || !email.includes("@")) {
      return res.send({
        code: 2,
        mes: "邮箱地址不合法",
      })
    }

    // 检测用户名是否存在
    const doc = await adminDB.findOne({ name })
    if (doc && doc.name !== name)
      return res.send({
        code: 2,
        mes: "该用户已存在",
      })
    // 检测邮箱
    const doc2 = await adminDB.findOne({ email })
    if (doc2 && doc2.email !== email)
      return res.send({
        code: 2,
        mes: "改邮箱已被注册",
      })

    if (phone === "暂无填写") phone = ""
    if (!occupation) occupation = "暂无职业"
    if (!des) des = "这个人很懒，什么都没有留下"
    await adminDB.findByIdAndUpdate(userID, {
      name,
      email,
      phone,
      occupation,
      des,
    })

    const newDoc = await adminDB.findById(userID)
    // 生成新的token
    const newToken = jwt.sign(
      {
        // 传入的数据
        _id: newDoc._id,
        name: newDoc.name,
        pass: newDoc.pass,
        // 有效时间
        exp: Math.floor(Date.now() / 1000) + 60 * 30, // 30分钟过期
      },
      cort
    )
    // 前端全局状态管理
    const vuexData = {
      _id: newDoc._id,
      name: newDoc.name,
      avatar: newDoc.avatar,
      des: newDoc.des,
      email: newDoc.email,
      cover: newDoc.cover,
      phone: newDoc.phone,
      supertube: newDoc.supertube,
      admintor: newDoc.admintor,
      time: newDoc.time,
      messageList: newDoc.messageList,
      occupation: newDoc.occupation,
      systemUnread: newDoc.systemUnread,
      festivalUnread: newDoc.festivalUnread,
      appointmentUnread: newDoc.appointmentUnread,
      startUnread: newDoc.startUnread,
    }
    // 存入操作日志 更新个人信息
    await journalDB.create({ author: userID, type: 2, operationType: 0 })

    res.send({
      code: 0,
      mes: "更新成功",
      data: {
        token: newToken,
        vuexData,
      },
    })
  } catch (error) {
    console.log(error)
    res.send({
      code: 5,
      mes: "服务器异常，请稍后再试",
    })
  }
})

// 修改密码
router.post("/updatePass", async (req, res) => {
  try {
    const { userID, oldPass, pass } = req.body
    // 校验旧密码是否符合格式
    if (!oldPass.trim() || oldPass.length < 6 || oldPass.length > 12) {
      return res.send({
        code: 2,
        mes: "输入密码不合法",
      })
    }
    if (!pass.trim() || pass.length < 6 || pass.length > 12) {
      return res.send({
        code: 2,
        mes: "输入密码不合法",
      })
    }
    // 查看密码是否正确
    const doc = await adminDB.findById(userID)
    if (doc.pass !== oldPass)
      return res.send({
        code: 4,
        mes: "原密码不正确",
      })
    // 修改
    await adminDB.findByIdAndUpdate(userID, {
      pass,
    })
    // 存入操作日志 用户修改密码
    await journalDB.create({ author: userID, type: 2, operationType: 1 })
    res.send({
      code: 0,
      mes: "密码已更新，请重新登录",
    })
  } catch (error) {
    res.send({
      code: 5,
      mes: "服务器异常，请稍后再试",
    })
  }
})

// 删除消息列表的信息
router.post("/delMes", async (req, res) => {
  try {
    // 用户ID 消息ID
    const { userID, mesID } = req.body
    const doc = await adminDB.findById(userID)
    // 检测消息是否存在
    const isMes = doc.messageList.id(mesID)
    if (!isMes)
      return res.send({
        code: 2,
        mes: "该消息已删除，请刷新重试",
      })
    await adminDB.findByIdAndUpdate(userID, {
      $pull: {
        messageList: { _id: mesID },
      },
    })
    res.send({
      code: 0,
      mes: "删除成功",
    })
  } catch (error) {
    res.send({
      code: 5,
      mes: "服务器异常，请稍后再试",
    })
  }
})

// 加入或移除消息列表的星标
router.post("/startMes", async (req, res) => {
  try {
    // 用户ID 消息ID 消息索引
    const { userID, mesID, mesIndex } = req.body
    const doc = await adminDB.findById(userID)
    // 检测消息是否存在
    const isMes = doc.messageList.id(mesID)
    if (!isMes)
      return res.send({
        code: 2,
        mes: "该消息已删除，请刷新重试",
      })
    // 判断星标是否存在该消息
    // 存在
    if (isMes.type === 3) {
      await adminDB.findByIdAndUpdate(userID, {
        $set: {
          [`messageList.${mesIndex}.type`]: isMes.constType,
        },
      })
    } else {
      // 不存在
      // 改变消息type
      await adminDB.findByIdAndUpdate(userID, {
        startUnread: doc.startUnread + 1,
        $set: {
          [`messageList.${mesIndex}.type`]: 3,
          [`messageList.${mesIndex}.ifStartRead`]: false,
        },
      })
    }

    // 加入或移除星标
    await adminDB.findByIdAndUpdate(userID, {
      $set: {
        [`messageList.${mesIndex}.ifMark`]: !isMes.ifMark,
      },
    })
    res.send({
      code: 0,
      mes: "修改状态成功",
    })
  } catch (error) {
    console.log(error)
    res.send({
      code: 5,
      mes: "服务器异常，请稍后再试",
    })
  }
})

// 消息以读未读处理
router.post("/readMes", async (req, res) => {
  try {
    // 用户ID 消息ID 消息索引
    const { userID, mesID, mesIndex, ifStart } = req.body
    const doc = await adminDB.findById(userID)
    // 检测消息是否存在
    const isMes = doc.messageList.id(mesID)
    if (!isMes)
      return res.send({
        code: 2,
        mes: "该消息已删除，请刷新重试",
      })
    // 消息已读处理
    // 星标处理
    if (ifStart) {
      // 未读
      if (!isMes.ifStartRead) {
        // 阅读信息为星标
        await adminDB.findByIdAndUpdate(userID, {
          $set: {
            [`messageList.${mesIndex}.ifStartRead`]: true,
            startUnread: doc.startUnread - 1,
          },
        })
      }
    }
    // 普通消息
    else {
      // 未读
      if (!isMes.ifRead) {
        switch (isMes.constType * 1) {
          case 0:
            await adminDB.findByIdAndUpdate(userID, {
              systemUnread: doc.systemUnread - 1,
            })
            break
          case 1:
            await adminDB.findByIdAndUpdate(userID, {
              festivalUnread: doc.festivalUnread - 1,
            })
            break
          case 2:
            await adminDB.findByIdAndUpdate(userID, {
              appointmentUnread: doc.appointmentUnread - 1,
            })
            break
        }
        await adminDB.findByIdAndUpdate(userID, {
          $set: {
            [`messageList.${mesIndex}.ifRead`]: true,
          },
        })
      }
    }
    res.send({
      code: 0,
      mes: "消息已读处理",
    })
  } catch (error) {
    console.log(error)
    res.send({
      code: 5,
      mes: "服务器异常,请稍后再试",
    })
  }
})

// 权限鉴别 鉴别是否为超级管理员
router.use(async (req, res, next) => {
  try {
    // 校验token
    // 获取请求头里面的token
    let token = (req.headers.authorization || "").slice(7)
    let info = null
    // 捕获错误
    try {
      info = jwt.verify(token, cort)
      const doc = await adminDB.findById(info._id)
      // 检测超管身份
      if (!doc.supertube)
        return res.send({
          code: 4,
          mes: "您不具有该权限",
        })
      if (!doc)
        return res.send({
          code: 4,
          mes: "系统检测到该账号已被注销",
        })
      // 检测密码是否更新
      if (info.pass !== doc.pass)
        return res.send({
          code: 4,
          mes: "密码已更新,请重新登录",
        })
      next()
    } catch (error) {
      return res.send({
        code: 4,
        mes: "登录信息已过期,请重新登录",
      })
    }
  } catch (error) {
    res.send({
      code: 5,
      mes: "服务器异常，请稍后再试",
    })
  }
})

router.use("/", require("./power"))

module.exports = router
